/**
 * TrialSoftware - 试用软件次数管理程序
 * 
 * 这个程序演示了如何通过文件持久化来管理软件的试用次数。
 * 主要功能包括：
 * 1. 记录软件使用次数
 * 2. 限制最大试用次数（默认10次）
 * 3. 提供购买正版功能，输入正确验证码后重置使用次数
 * 4. 显示使用信息和剩余次数
 * 
 * 程序使用文件读写操作来持久化保存使用次数，即使程序关闭后重新启动，
 * 也能正确记录使用次数。
 * 
 * 技术要点：
 * - 使用BufferedReader/BufferedWriter进行高效的文件读写
 * - 使用try-with-resources语句自动管理资源
 * - 异常处理确保程序在文件操作失败时仍能正常运行
 * - 面向对象的设计原则，将功能分解为独立的方法
 */
package day29.homework;

import java.io.*;
import java.util.Scanner;

/**
 * 试用软件次数管理程序主类
 * 
 * 该类负责管理软件的试用次数，包括：
 * - 读取和保存使用次数到文件
 * - 检查试用次数是否超过限制
 * - 处理用户购买正版的流程
 * - 执行软件的主要功能
 * 
 * 程序采用静态方法设计，所有功能都通过静态方法实现，
 * 便于直接从main方法调用，无需实例化对象。
 */
public class TrialSoftware {
    // 定义存储使用次数的文件名常量
    // 使用private访问修饰符确保该常量只能在本类中访问
    // 使用static关键字使该变量属于类而不是实例
    // 使用final关键字确保该值不可更改
    private static final String COUNT_FILE = "usage_count.txt";
    
    // 定义最大试用次数限制常量
    // 当用户使用次数达到该值时，需要购买正版才能继续使用
    private static final int MAX_TRIALS = 10;
    
    // 定义购买正版的验证码常量
    // 用户输入此验证码表示购买正版，将重置使用次数
    private static final int PURCHASE_CODE = 520;
    
    /**
     * 程序主入口方法
     * 
     * 这是程序的起点，控制整个软件试用逻辑和用户交互流程。
     * 方法执行步骤：
     * 1. 从文件中读取当前已使用的次数
     * 2. 判断是否超过试用次数限制
     * 3. 如果超过限制，提示用户购买正版并验证验证码
     * 4. 如果未超过限制，增加使用次数并保存
     * 5. 执行软件的主要功能
     * 
     * @param args 命令行参数数组，用于接收从命令行传入的参数
     *             在本程序中未使用，但作为main方法的标准签名保留
     */
    public static void main(String[] args) {
        // 调用readUsageCount方法从文件中读取当前使用次数
        // 如果文件不存在或读取失败，该方法会返回默认值0
        int usageCount = readUsageCount();
        
        // 判断当前使用次数是否大于或等于最大试用次数
        // 这是一个关键的条件判断，决定程序执行哪个分支
        if (usageCount >= MAX_TRIALS) {
            // 用户已超过试用次数限制，进入购买正版流程
            
            // 向控制台输出提示信息，告知用户试用次数已用完
            // 使用System.out.println方法将信息输出到标准输出流（通常是控制台）
            System.out.println("您已超过试用次数，请购买正版软件！");
            
            // 提示用户输入购买码
            System.out.println("请输入购买码(输入520代表购买正版)：");
            
            // 创建Scanner对象用于读取用户从控制台输入的数据
            // Scanner是Java标准库中用于解析基本类型和字符串的简单文本扫描器
            Scanner scanner = new Scanner(System.in);
            
            // 调用scanner.nextInt()方法读取用户输入的整数
            // 该方法会阻塞程序执行，直到用户输入一个整数并按回车键
            int code = scanner.nextInt();
            
            // 验证用户输入的验证码是否与预设的购买码一致
            // 使用==运算符比较两个int值是否相等
            if (code == PURCHASE_CODE) {
                // 用户输入了正确的购买码，验证成功
                
                // 向用户表示感谢，确认购买正版成功
                System.out.println("感谢您购买正版软件！您可以继续使用本软件。");
                
                // 重置使用次数为0，允许用户重新开始计数
                usageCount = 0;
                
                // 调用writeUsageCount方法将重置后的次数写入文件保存
                // 确保下次启动程序时能从0开始计数
                writeUsageCount(usageCount);
            } else {
                // 用户输入的购买码不正确，验证失败
                
                // 提示用户购买码错误
                System.out.println("购买码错误，程序即将退出。");
                
                // 使用return语句直接结束main方法，程序退出
                // 这是处理错误情况的一种方式，避免程序继续执行
                return;
            }
        } else {
            // 用户未超过试用次数限制，正常增加使用次数
            
            // 将使用次数加1，表示本次启动程序的使用
            usageCount++;
            
            // 调用writeUsageCount方法将更新后的次数写入文件保存
            // 确保下次启动程序时能获取到正确的使用次数
            writeUsageCount(usageCount);
            
            // 显示欢迎信息，告知用户这是第几次使用软件
            // 使用字符串连接操作符"+"将文本和变量值组合成完整信息
            System.out.println("欢迎使用本软件！这是您第 " + usageCount + " 次使用。");
            
            // 显示剩余试用次数信息
            // 通过减法运算计算剩余次数并显示给用户
            System.out.println("剩余试用次数: " + (MAX_TRIALS - usageCount));
        }
        
        // 执行软件的主要功能
        // 无论用户是试用还是已购买正版，都会执行此方法
        runSoftware();
    }
    
    /**
     * 从文件中读取软件使用次数
     * 
     * 该方法负责从指定的文件中读取软件的使用次数。
     * 使用了Java 7引入的try-with-resources语句来自动管理资源，
     * 确保文件流在使用完毕后能自动关闭，避免资源泄露。
     * 
     * 方法执行步骤：
     * 1. 创建FileReader和BufferedReader对象用于读取文件
     * 2. 读取文件第一行内容
     * 3. 将读取的字符串转换为整数
     * 4. 返回转换后的整数值作为使用次数
     * 5. 如果发生异常（文件不存在、格式错误等），返回默认值0
     * 
     * @return 当前使用次数，如果读取失败则返回0
     *         返回值类型为int，表示使用次数是一个整数
     */
    private static int readUsageCount() {
        // 使用try-with-resources语句创建BufferedReader对象
        // 括号中的资源会在try语句块执行完毕后自动关闭
        // 这种方式比手动关闭资源更安全、更简洁
        try (BufferedReader reader = new BufferedReader(new FileReader(COUNT_FILE))) {
            // 调用reader.readLine()方法读取文件的第一行内容
            // 该方法返回一个String类型的值，表示读取到的一行文本
            // 然后使用Integer.parseInt()方法将字符串转换为整数
            // 最后将转换结果作为方法的返回值
            return Integer.parseInt(reader.readLine());
        } catch (IOException | NumberFormatException e) {
            // 捕获可能发生的两种异常：
            // IOException：文件读取相关异常，如文件不存在、无权限等
            // NumberFormatException：数字格式异常，如文件内容不是有效数字
            
            // 当捕获到异常时，向标准错误流输出错误信息
            // 使用e.getMessage()获取异常的具体描述信息
            System.err.println("读取使用次数失败: " + e.getMessage());
            
            // 发生异常时返回默认值0，表示软件尚未使用过或计数器重置
            // 这确保了即使文件操作失败，程序也能继续正常运行
            return 0;
        }
    }
    
    /**
     * 将使用次数写入文件保存
     * 
     * 该方法负责将当前的使用次数写入到指定文件中进行持久化保存。
     * 同样使用try-with-resources语句来自动管理文件写入流资源。
     * 
     * 方法执行步骤：
     * 1. 创建FileWriter和BufferedWriter对象用于写入文件
     * 2. 将使用次数转换为字符串格式
     * 3. 将字符串写入文件
     * 4. 如果发生异常，输出错误信息
     * 
     * @param count 要保存的使用次数
     *              参数类型为int，表示要写入文件的整数值
     */
    private static void writeUsageCount(int count) {
        // 使用try-with-resources语句创建BufferedWriter对象
        // 这确保了即使在写入过程中发生异常，文件流也能正确关闭
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(COUNT_FILE))) {
            // 调用String.valueOf()方法将整数转换为字符串
            // 然后调用writer.write()方法将字符串写入文件
            // FileWriter会自动创建文件（如果不存在）或覆盖现有文件内容
            writer.write(String.valueOf(count));
        } catch (IOException e) {
            // 捕获文件写入过程中可能发生的IOException异常
            // 如磁盘空间不足、无写入权限等
            
            // 当文件写入失败时，向标准错误流输出详细的错误信息
            // 包括具体的异常描述，有助于调试和问题定位
            System.err.println("保存使用次数失败: " + e.getMessage());
        }
    }
    
    /**
     * 运行软件主要功能
     * 
     * 该方法负责执行软件的实际业务逻辑。
     * 在当前实现中，仅输出一些演示信息。
     * 在实际应用中，这里应该包含软件的核心功能代码。
     * 
     * 方法执行步骤：
     * 1. 输出软件正在运行的提示信息
     * 2. 显示软件的功能说明
     * 3. （在实际应用中）执行软件的核心业务逻辑
     */
    private static void runSoftware() {
        // 输出软件运行提示信息
        System.out.println("软件正在运行...");
        
        // 输出软件功能说明信息
        System.out.println("这是一个演示程序，具有10次免费试用限制。");
        System.out.println("试用次数用完后需要输入购买码520才能继续使用。");
        
        // TODO: 这里可以添加软件的实际功能实现
        // 例如：数据处理、计算、用户交互等核心业务逻辑
    }
}